package com.ruoyi.project.service.impl;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.List;

import com.ruoyi.common.domainenum.FinSubjectDirectionType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.project.common.StaticMethod;
import com.ruoyi.project.domain.FinRecordVoucher;
import com.ruoyi.project.domain.FinRecordVoucherItem;
import com.ruoyi.project.domain.FinSubject;
import com.ruoyi.project.mapper.FinRecordVoucherItemMapper;
import liquibase.pro.packaged.B;
import org.apache.poi.ss.usermodel.*;
import org.springframework.stereotype.Service;
import com.ruoyi.common.utils.SecurityUtils;
import javax.annotation.Resource;
import com.ruoyi.project.mapper.FinSubjectMonthMapper;
import com.ruoyi.project.domain.FinSubjectMonth;
import com.ruoyi.project.service.IFinSubjectMonthService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 科目余额Service业务层处理
 *
 * @author abel
 * @date 2024-10-15
 */
@Service
public class FinSubjectMonthServiceImpl implements IFinSubjectMonthService
{
    @Resource
    private FinSubjectMonthMapper finSubjectMonthMapper;
    @Resource
    private FinRecordVoucherItemMapper finRecordVoucherItemMapper;
    /**
     * 查询科目余额
     *
     * @param id 科目余额ID
     * @return 科目余额
     */
    @Override
    public FinSubjectMonth selectFinSubjectMonthById(Long id)
    {
        return finSubjectMonthMapper.selectById(id);
    }



    /**
     * 获取科目余额，获取不到数据抛错
     *
     * @param id 科目余额ID
     * @return 科目余额
     */
    @Override
    public FinSubjectMonth getFinSubjectMonthById(Long id)
    {
        FinSubjectMonth finSubjectMonth = finSubjectMonthMapper.selectById(id);
        if(finSubjectMonth == null){
            throw new ServiceException("科目余额id不正确，没有找到相关数据！");
        }
        return finSubjectMonth;
    }

    /**
     * 查询科目余额列表
     *
     * @param finSubjectMonth 科目余额
     * @return 科目余额
     */
    @Override
    public List<FinSubjectMonth> selectFinSubjectMonthList(FinSubjectMonth finSubjectMonth)
    {
        return finSubjectMonthMapper.selectFinSubjectMonthList(finSubjectMonth);
    }

    /**
     * 新增科目余额
     *
     * @param finSubjectMonth 科目余额
     * @return 结果
     */
    @Override
    @Transactional
    public int importDefaultFinSubjectMonth(FinSubjectMonth finSubjectMonth)
    {
        finSubjectMonth.setCreateTime(DateUtils.getNowDate());
        finSubjectMonth.setCreateBy(SecurityUtils.getUsername());
        finSubjectMonth.setCreateId(SecurityUtils.getUserId());;
        finSubjectMonth.setUpdateBy(SecurityUtils.getUsername());
        finSubjectMonth.setUpdateId(SecurityUtils.getUserId());
        finSubjectMonth.setUpdateTime(DateUtils.getNowDate());
        return finSubjectMonthMapper.insert(finSubjectMonth);
    }

    /**
     * 修改科目余额
     *
     * @param finSubjectMonth 科目余额
     * @return 结果
     */
    @Override
    @Transactional
    public int updateFinSubjectMonth(FinSubjectMonth finSubjectMonth)
    {
        finSubjectMonth.setUpdateBy(SecurityUtils.getUsername());
        finSubjectMonth.setUpdateId(SecurityUtils.getUserId());
        finSubjectMonth.setUpdateTime(DateUtils.getNowDate());
        return finSubjectMonthMapper.updateById(finSubjectMonth);
    }

    /**
     * 批量删除科目余额
     *
     * @param ids 需要删除的科目余额ID
     * @return 结果
     */
    @Override
    public int deleteFinSubjectMonthByIds(Long[] ids)
    {
        for(Long id:ids){
            deleteFinSubjectMonthById(id);
        }
        return ids.length;
    }

    /**
     * 删除科目余额信息
     *
     * @param id 科目余额ID
     * @return 结果
     */
    @Override
    public int deleteFinSubjectMonthById(Long id)
    {
        return finSubjectMonthMapper.deleteFinSubjectMonthById(id);
    }

    @Override
    public FinSubjectMonth createBySubject(FinSubject finSubject,int year,int month) {
        FinSubjectMonth subjectMonth = finSubjectMonthMapper.findByInfo(finSubject.getPackageId(),finSubject.getId(),year,month);
        if(subjectMonth==null){
            subjectMonth = new FinSubjectMonth();
            setFinSubjectField(subjectMonth,finSubject);
            subjectMonth.setYearValue(year);
            subjectMonth.setMonthValue(month);
            subjectMonth.setYearAndMonth(StaticMethod.genYearAndMonth(year,month));
            subjectMonth.setPackageId(finSubject.getPackageId());
            subjectMonth.setSubjectLevel(finSubject.getSubjectLevel());
            StaticMethod.setCreateField(subjectMonth,SecurityUtils.getUserId(),SecurityUtils.getUsername());
            finSubjectMonthMapper.insert(subjectMonth);
        }else{
            updateBySubject(finSubject);
        }
        return subjectMonth;
    }

    @Override
    public FinSubjectMonth findBySubjectInfo(FinSubject finSubject, int year, int month) {
        return finSubjectMonthMapper.findByInfo(finSubject.getPackageId(),finSubject.getId(),year,month);
    }

    private void setFinSubjectField(FinSubjectMonth subjectMonth, FinSubject finSubject){
        subjectMonth.setSubjectId(finSubject.getId());
        subjectMonth.setSubjectName(finSubject.getName());
        subjectMonth.setSubjectCode(finSubject.getCode());
        subjectMonth.setSubjectType(finSubject.getSubjectType());
        subjectMonth.setDirectionType(finSubject.getDirectionType());
        subjectMonth.setSubjectParentId(finSubject.getParentId());
        subjectMonth.setSubjectParentName(finSubject.getParentName());
        subjectMonth.setSubjectParentCode(finSubject.getParentCode());
    }

    @Override
    public void updateBySubject(FinSubject finSubject) {
        finSubjectMonthMapper.updateBySubjectId(finSubject.getId(),finSubject.getCode(),finSubject.getName(),finSubject.getDirectionType(),finSubject.getSubjectLevel());
    }

    @Override
    public void importDefaultFinSubjectMonth(Long packageId, int year, int month) throws IOException {
        InputStream inputStream = Thread.currentThread()
                .getContextClassLoader()
                .getResourceAsStream("init-data/init-month.xlsx");
        Workbook wb = WorkbookFactory.create(inputStream);
        Sheet sheet = wb.getSheetAt(0);
        for(int i=0;i<70;i++){
            Row row = sheet.getRow(i);
            if(row==null){
                continue;
            }
            Cell cell = row.getCell(0);
            if(cell.getCellType() == CellType.STRING){
                String code = cell.getStringCellValue();
                if(StringUtils.isBlank(code)){
                    continue;
                }
                FinSubjectMonth finSubjectMonth = finSubjectMonthMapper.findByInfoCode(packageId,code,year,month);
                if(finSubjectMonth!=null){
                    finSubjectMonth.setBeginJieValue(getNumberValue(row.getCell(2)));
                    finSubjectMonth.setBeginDaiValue(getNumberValue(row.getCell(3)));

                    finSubjectMonth.setMonthJieValue(getNumberValue(row.getCell(4)));
                    finSubjectMonth.setMonthDaiValue(getNumberValue(row.getCell(5)));
                    finSubjectMonth.setYearJieValue(getNumberValue(row.getCell(6)));
                    finSubjectMonth.setYearDaiValue(getNumberValue(row.getCell(7)));

                    finSubjectMonth.setEndJieValue(getNumberValue(row.getCell(8)));
                    finSubjectMonth.setEndDaiValue(getNumberValue(row.getCell(8)));
                    finSubjectMonthMapper.updateById(finSubjectMonth);
                }
            }
        }
    }

    private BigDecimal getNumberValue(Cell cell){
        BigDecimal res = BigDecimal.ZERO;
        if(cell.getCellType() == CellType.NUMERIC){
            res = new BigDecimal(cell.getNumericCellValue());
        }else {
            String v = cell.getStringCellValue();
            if(StringUtils.isNotBlank(v)){
                res = new BigDecimal(v);
            }
        }
        return res;
    }

    @Transactional
    @Override
    public void recordToBook(FinRecordVoucher finRecordVoucher) {
        List<FinRecordVoucherItem> itemList = finRecordVoucherItemMapper.listByRecordId(finRecordVoucher.getId());
        itemList.forEach(item->{
            FinSubjectMonth finSubjectMonth = finSubjectMonthMapper.findByInfo(finRecordVoucher.getPackageId(),item.getSubjectId()
                    ,finRecordVoucher.getYearValue(),finRecordVoucher.getMonthValue());

            while (finSubjectMonth!=null) {
                finSubjectMonth.setEndJieValue(finSubjectMonth.getEndJieValue().add(item.getJieAmount()));
                finSubjectMonth.setEndDaiValue(finSubjectMonth.getEndDaiValue().add(item.getDaiAmount()));
                finSubjectMonth.setMonthJieValue(finSubjectMonth.getMonthJieValue().add(item.getJieAmount()));
                finSubjectMonth.setMonthDaiValue(finSubjectMonth.getMonthDaiValue().add(item.getDaiAmount()));
                finSubjectMonth.setYearJieValue(finSubjectMonth.getYearJieValue().add(item.getJieAmount()));
                finSubjectMonth.setYearDaiValue(finSubjectMonth.getYearDaiValue().add(item.getDaiAmount()));

                if (finSubjectMonth.getDirectionType() == FinSubjectDirectionType.JIE) {
                    finSubjectMonth.setMonthSumValue(item.getJieAmount().subtract(item.getDaiAmount()));
                } else {
                    finSubjectMonth.setMonthSumValue(item.getDaiAmount().subtract(item.getJieAmount()));
                }
                finSubjectMonthMapper.updateById(finSubjectMonth);
                if(finSubjectMonth.getSubjectParentId()!=null){
                    finSubjectMonth = finSubjectMonthMapper.findByInfo(finRecordVoucher.getPackageId(),finSubjectMonth.getSubjectParentId()
                            ,finRecordVoucher.getYearValue(),finRecordVoucher.getMonthValue());
                }
            }
        });
    }

    @Transactional
    @Override
    public void recordCancelToBook(FinRecordVoucher finRecordVoucher) {
        List<FinRecordVoucherItem> itemList = finRecordVoucherItemMapper.listByRecordId(finRecordVoucher.getId());
        itemList.forEach(item->{
            FinSubjectMonth finSubjectMonth = finSubjectMonthMapper.findByInfo(finRecordVoucher.getPackageId(),item.getSubjectId()
                    ,finRecordVoucher.getYearValue(),finRecordVoucher.getMonthValue());
            while (finSubjectMonth!=null) {
                finSubjectMonth.setEndJieValue(finSubjectMonth.getEndJieValue().subtract(item.getJieAmount()));
                finSubjectMonth.setEndDaiValue(finSubjectMonth.getEndDaiValue().subtract(item.getDaiAmount()));
                finSubjectMonth.setMonthJieValue(finSubjectMonth.getMonthJieValue().subtract(item.getJieAmount()));
                finSubjectMonth.setMonthDaiValue(finSubjectMonth.getMonthDaiValue().subtract(item.getDaiAmount()));
                finSubjectMonth.setYearJieValue(finSubjectMonth.getYearJieValue().subtract(item.getJieAmount()));
                finSubjectMonth.setYearDaiValue(finSubjectMonth.getYearDaiValue().subtract(item.getDaiAmount()));

                if(finSubjectMonth.getDirectionType()==FinSubjectDirectionType.JIE){
                    finSubjectMonth.setMonthSumValue(item.getJieAmount().subtract(item.getDaiAmount()).multiply(new BigDecimal(-1)));
                }else{
                    finSubjectMonth.setMonthSumValue(item.getDaiAmount().subtract(item.getJieAmount()).multiply(new BigDecimal(-1)));
                }
                finSubjectMonthMapper.updateById(finSubjectMonth);
                if(finSubjectMonth.getSubjectParentId()!=null){
                    finSubjectMonth = finSubjectMonthMapper.findByInfo(finRecordVoucher.getPackageId(),finSubjectMonth.getSubjectParentId()
                            ,finRecordVoucher.getYearValue(),finRecordVoucher.getMonthValue());
                }
            }
        });
    }
}
